# -*-coding: utf-8 -*-
"""
日志记录工具
"""
import datetime
import logging
import logging.handlers
import os
import sys
from pathlib import Path

ROOT_DIR = os.getcwd()


class MyFormatter(logging.Formatter):
    converter = datetime.datetime.fromtimestamp

    def formatTime(self, record, datefmt=None):
        ct = self.converter(record.created)
        if datefmt:
            s = ct.strftime(datefmt)
        else:
            t = ct.strftime("%Y-%m-%d %H:%M:%S")
            s = "%s.%03d" % (t, record.msecs)
        return s


class LogUtil:

    def __init__(self, modular_name="arknovv-test", console_output=False):
        """
           Args:
               output (str): a file name or a directory to save log. If None, will not save log file.
                   If ends with ".txt" or ".log", assumed to be a file name.
                   Otherwise, logs will be saved to `logs/20210621.txt`.
        """
        # 基础日志等级
        self.log_level = logging.DEBUG
        # 窗口日志流
        self.console_output = console_output
        # 日志文件后缀名
        self.log_suffix = ".log"
        # 日志文件路径
        self.log_path = Path(ROOT_DIR) / "logs" / f"{modular_name}{self.log_suffix}"
        # 日志内容格式
        self.formatter = '%(asctime)s | %(levelname)s | %(thread)d | %(filename)s[:%(lineno)d] - %(funcName)s: %(' \
                         'message)s '
        # 时间格式化
        self.data_format = "%Y-%m-%d %H:%M:%S.%f"

        # 初始化
        logger = logging.getLogger(modular_name)
        # 设置日志基础级别
        logger.setLevel(self.log_level)
        #
        logger.propagate = 1

        # 格式化
        plain_formatter = MyFormatter(fmt=self.formatter, datefmt=self.data_format)

        # 判断目录是否存在
        if not os.path.exists(os.path.dirname(self.log_path)):
            os.makedirs(os.path.dirname(self.log_path))

        # 判断文件是否存在
        if not os.path.exists(self.log_path):
            fp = open(self.log_path, "w+")
            fp.close()

        # 按日期切割日志
        # filename：日志文件名
        # when：日志文件按什么维度切分。'S'-秒；'M'-分钟；'H'-小时；'D'-天；'W'-周
        #       这里需要注意，如果选择 D-天，那么这个不是严格意义上的'天'，而是从你
        #       项目启动开始，过了24小时，才会从新创建一个新的日志文件，
        #       如果项目重启，这个时间就会重置。所以这里选择'MIDNIGHT'-是指过了午夜
        #       12点，就会创建新的日志
        # interval：是指等待多少个单位 when 的时间后，Logger会自动重建文件。
        # backupCount：是保留日志个数。默认的0是不会自动删除掉日志
        fh = logging.handlers.TimedRotatingFileHandler(filename=self.log_path,
                                                       when='D',
                                                       interval=1,
                                                       backupCount=8,
                                                       encoding='utf-8')
        # 设置日志等级
        fh.setLevel(self.log_level)
        # 设置日志格式
        fh.setFormatter(plain_formatter)
        # 添加文件处理器到Logger
        logger.addHandler(fh)

        # 如果需要在控制台输出日志
        if self.console_output:
            # 创建StreamHandler对象
            console = logging.StreamHandler(stream=sys.stdout)
            # 设置控制台日志级别
            console.setLevel(self.log_level)
            # 设置控制台日志格式
            console.setFormatter(plain_formatter)
            # 添加控制台处理器到Logger
            logger.addHandler(console)

            logger.addHandler(console)

        self.log = logger

    def get_log_object(self):
        """
        获取日志对象
        """
        return self.log

    def debug(self, message: str, data=""):
        """
        记录调试信息

        :param message: 日志消息。
        :param data: 附加数据，默认为空字符串。
        """
        self.log.debug(f"{message} {data}")

    def info(self, message: str, data=""):
        """
        记录一般信息
        :param message: 日志消息。
        :param data: 附加数据，默认为空字符串。
        """
        self.log.info(f"{message} {data}")

    def warning(self, message: str, data=""):
        """
        记录警告信息
        :param message: 日志消息。
        :param data: 附加数据，默认为空字符串。
        """
        self.log.warning(f"{message} {data}")

    def error(self, message: str, data=""):
        """
        记录错误信息
        :param message: 日志消息。
        :param data: 附加数据，默认为空字符串。
        """
        self.log.error(f"{message} {data}")

    def critical(self, message: str, data=""):
        """
        记录严重错误信息
        :param message: 日志消息
        :param data: 附加数据，默认空字符串
        """
        self.log.critical(f"{message} {data}")


# 初始化日志工具
log_util = LogUtil(console_output=True)
log = log_util.get_log_object()
